#include "log.h"
#include "ioengine.h"
#include "st_pio.h"
#include "f-ops.h"
#include "ioengine.h"
//#include "st-posix-aio.h"

class Pio : public IOEngine
{
public:
	Pio();
	~Pio();
	ssize_t pread(int fd, void *buf, size_t count, off_t offset);
	ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
	ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	int fdatasync(int fd);
	int fsync(int fd);
};

class Libaio : public IOEngine
{
public:
	Libaio();
	~Libaio();
	ssize_t pread(int fd, void *buf, size_t count, off_t offset);
	ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
	ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	int fdatasync(int fd);
	int fsync(int fd);
};

class IgnoreIo : public IOEngine
{
public:
	IgnoreIo();
	~IgnoreIo();
	ssize_t pread(int fd, void *buf, size_t count, off_t offset);
	ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
	ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
	int fdatasync(int fd);
	int fsync(int fd);
};

Pio::Pio()
{
	LOG_DEBUG("Pio constructor");
}

Pio::~Pio()
{
	LOG_DEBUG("Pio destructor");
}

ssize_t Pio::pread(int fd, void *buf, size_t count, off_t offset)
{
	return st_pread(fd, buf, count, offset);
}

ssize_t Pio::pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	return st_pwrite(fd, buf, count, offset);
}

ssize_t Pio::preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_preadv(fd, iov, iovcnt, offset);
}

ssize_t Pio::pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_pwritev(fd, iov, iovcnt, offset);
}

int Pio::fdatasync(int fd)
{
	return st_fdatasync(fd);
}

int Pio::fsync(int fd)
{
	return st_fsync(fd);
}


Libaio::Libaio()
{
	st_pio_init();
}

Libaio::~Libaio()
{
	st_pio_fini();
}

ssize_t Libaio::pread(int fd, void *buf, size_t count, off_t offset)
{
	return st_libaio_pread(fd, buf, count, offset);
}

ssize_t Libaio::pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	return st_libaio_pwrite(fd, buf, count, offset);
}

ssize_t Libaio::preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_libaio_preadv(fd, iov, iovcnt, offset);
}

ssize_t Libaio::pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_libaio_pwritev(fd, iov, iovcnt, offset);
}

int Libaio::fdatasync(int fd)
{
	return st_libaio_fdsync(fd);
}

int Libaio::fsync(int fd)
{
	return st_libaio_fsync(fd);
}

IgnoreIo::IgnoreIo()
{
	LOG_DEBUG("IgnoreIo constructor");
}

IgnoreIo::~IgnoreIo()
{
	LOG_DEBUG("IgnoreIo destructor");
}

ssize_t IgnoreIo::pread(int fd, void *buf, size_t count, off_t offset)
{
	return st_ignore_pread(fd, buf, count, offset);
}

ssize_t IgnoreIo::pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	return st_ignore_pwrite(fd,  buf, count, offset);
}

ssize_t IgnoreIo::preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_ignore_preadv(fd, iov, iovcnt, offset);
}

ssize_t IgnoreIo::pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	return st_ignore_pwritev(fd, iov, iovcnt, offset);
}

int IgnoreIo::fdatasync(int fd)
{
	return st_ignore_fdatasync(fd);
}

int IgnoreIo::fsync(int fd)
{
	return st_ignore_fsync(fd);
}

Pio _pio;
IOEngine* ng_pio = &_pio;
IOEngine* ng_libaio;
IOEngine* ng_ignore;

IOEngine* ioengine = ng_pio;


void enable_libaio(void)
{
	ng_libaio = new Libaio();
	ioengine = ng_libaio;
}

void enable_ignore_ops(void)
{
	ng_ignore = new IgnoreIo();
	ioengine = ng_ignore;
}
